package com.mydemo.utils.base2.mp4towav03;



/**
 * 带音频质量检查的增强版本
 */
import java.io.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EnhancedAudioProcessor {

    /**
     * 音频文件信息类，用于存储音频的详细信息
     */
    public static class AudioInfo {
        private String format;
        private String codec;
        private int sampleRate;
        private int channels;
        private String duration;
        private String bitrate;
        private boolean isValid;

        // Getters and Setters
        public String getFormat() { return format; }
        public void setFormat(String format) { this.format = format; }

        public String getCodec() { return codec; }
        public void setCodec(String codec) { this.codec = codec; }

        public int getSampleRate() { return sampleRate; }
        public void setSampleRate(int sampleRate) { this.sampleRate = sampleRate; }

        public int getChannels() { return channels; }
        public void setChannels(int channels) { this.channels = channels; }

        public String getDuration() { return duration; }
        public void setDuration(String duration) { this.duration = duration; }

        public String getBitrate() { return bitrate; }
        public void setBitrate(String bitrate) { this.bitrate = bitrate; }

        public boolean isValid() { return isValid; }
        public void setValid(boolean valid) { isValid = valid; }

        @Override
        public String toString() {
            return String.format(
                    "音频信息: 格式=%s, 编码=%s, 采样率=%dHz, 声道=%d, 时长=%s, 比特率=%s, 有效=%s",
                    format, codec, sampleRate, channels, duration, bitrate, isValid
            );
        }

        /**
         * 检查音频是否符合Vosk处理要求
         */
        public boolean meetsVoskRequirements() {
            return isValid && sampleRate == 16000 && channels == 1;
        }

        /**
         * 获取音频质量评分 (1-10分)
         */
        public int getQualityScore() {
            int score = 0;
            if (isValid) score += 3;
            if (sampleRate >= 16000) score += 3;
            if (channels == 1) score += 2;
            if (bitrate != null && bitrate.contains("kb/s")) {
                try {
                    int kbRate = Integer.parseInt(bitrate.replaceAll("[^0-9]", ""));
                    if (kbRate >= 128) score += 2;
                } catch (NumberFormatException e) {
                    // 忽略解析错误
                }
            }
            return score;
        }
    }

    /**
     * 智能音频处理：根据输入格式自动选择最佳处理方式
     */
    public static String smartAudioProcessing(String inputFilePath) throws Exception {
        File inputFile = new File(inputFilePath);
        if (!inputFile.exists()) {
            throw new FileNotFoundException("输入文件不存在: " + inputFilePath);
        }

        // 先检查音频质量
        AudioInfo audioInfo = getDetailedAudioInfo(inputFilePath);
        System.out.println("原始音频信息: " + audioInfo);
        System.out.println("音频质量评分: " + audioInfo.getQualityScore() + "/10");

        // 即使解析失败，也尝试处理文件，因为文件可能实际上是有效的
        if (!audioInfo.isValid()) {
            System.err.println("警告：无法完全解析音频信息，但将继续尝试处理文件");
            // 不抛出异常，继续处理
        }

        String fileName = inputFile.getName().toLowerCase();
        String outputPath = inputFile.getParent() + File.separator + "processed_" +
                inputFile.getName().replaceFirst("[.][^.]+$", "") + ".wav";

        boolean success;

        if (fileName.endsWith(".mp4") || fileName.endsWith(".mov") || fileName.endsWith(".avi")) {
            System.out.println("检测到视频文件，提取并优化音频...");
            success = extractAndOptimizeAudio(inputFilePath, outputPath);
        } else if (fileName.endsWith(".wav")) {
            if (audioInfo.isValid() && audioInfo.meetsVoskRequirements()) {
                System.out.println("WAV文件已符合Vosk要求，无需额外处理");
                return inputFilePath; // 直接返回原文件
            } else {
                System.out.println("WAV文件进行优化处理...");
                success = optimizeWavAudio(inputFilePath, outputPath);
            }
        } else if (fileName.endsWith(".m4a") || fileName.endsWith(".aac") ||
                fileName.endsWith(".mp3") || fileName.endsWith(".flac")) {
            System.out.println("检测到音频文件，转换为优化WAV...");
            success = convertToOptimizedWav(inputFilePath, outputPath);
        } else {
            throw new UnsupportedOperationException("不支持的音频格式: " + fileName);
        }

        if (!success) {
            throw new RuntimeException("音频处理失败");
        }

        // 验证输出文件质量
        AudioInfo outputInfo = getDetailedAudioInfo(outputPath);
        System.out.println("处理后音频信息: " + outputInfo);
        System.out.println("处理后质量评分: " + outputInfo.getQualityScore() + "/10");

        if (outputInfo.isValid() && !outputInfo.meetsVoskRequirements()) {
            System.err.println("警告：输出文件可能不完全符合Vosk要求");
        }

        return outputPath;
    }

    /**
     * 从视频文件提取并优化音频
     */
    public static boolean extractAndOptimizeAudio(String inputPath, String outputPath) {
        ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg",
                "-i", inputPath,
                "-vn",                    // 不处理视频
                "-ar", "16000",           // 采样率16kHz
                "-ac", "1",               // 单声道
                "-c:a", "pcm_s16le",      // PCM 16位编码
                "-af", "highpass=f=80,lowpass=f=8000,compand=attacks=0:decays=0.3:points=-80/-80|-30/-10|-20/-5|0/0",
                "-acodec", "pcm_s16le",
                "-y",                     // 覆盖输出文件
                outputPath
        );

        return executeFFmpegCommand(processBuilder, "视频提取音频");
    }

    /**
     * 优化WAV音频文件
     */
    public static boolean optimizeWavAudio(String inputPath, String outputPath) {
        ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg",
                "-i", inputPath,
                "-ar", "16000",
                "-ac", "1",
                "-c:a", "pcm_s16le",
                "-af", "highpass=f=80,lowpass=f=8000,compand=attacks=0:decays=0.3:points=-80/-80|-30/-10|-20/-5|0/0",
                "-acodec", "pcm_s16le",
                "-y",
                outputPath
        );

        return executeFFmpegCommand(processBuilder, "WAV优化");
    }

    /**
     * 将其他音频格式转换为优化WAV
     */
    public static boolean convertToOptimizedWav(String inputPath, String outputPath) {
        ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg",
                "-i", inputPath,
                "-ar", "16000",
                "-ac", "1",
                "-c:a", "pcm_s16le",
                "-af", "highpass=f=80,lowpass=f=8000",
                "-y",
                outputPath
        );

        return executeFFmpegCommand(processBuilder, "音频格式转换");
    }

    /**
     * 获取详细的音频文件信息
     */
    public static AudioInfo getDetailedAudioInfo(String audioPath) {
        AudioInfo info = new AudioInfo();

        ProcessBuilder processBuilder = new ProcessBuilder(
                "ffmpeg",
                "-i", audioPath
        );

        try {
            Process process = processBuilder.start();
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

            StringBuilder output = new StringBuilder();
            String line;
            while ((line = errorReader.readLine()) != null) {
                output.append(line).append("\n");
            }

            process.waitFor(10, TimeUnit.SECONDS);

            // 解析FFmpeg输出
            parseFFmpegOutput(output.toString(), info);

        } catch (IOException | InterruptedException e) {
            System.err.println("获取音频信息失败: " + e.getMessage());
            info.setValid(false);
        }

        return info;
    }

    /**
     * 解析FFmpeg输出，提取音频信息 - 修复版本
     */
    private static void parseFFmpegOutput(String output, AudioInfo info) {
        info.setValid(false);

        try {
            // 首先检查是否有错误信息
            if (output.contains("Invalid data found") || output.contains("could not find codec")) {
                System.err.println("FFmpeg报告文件格式错误");
                return;
            }

            // 解析格式 - 更通用的匹配
            Pattern formatPattern = Pattern.compile("Input #\\d+,?\\s*([^,]+),?\\s*from");
            Matcher formatMatcher = formatPattern.matcher(output);
            if (!formatMatcher.find()) {
                // 尝试其他格式模式
                formatPattern = Pattern.compile("Input #\\d+,\\s*([^,]+),");
                formatMatcher = formatPattern.matcher(output);
            }
            if (formatMatcher.find()) {
                info.setFormat(formatMatcher.group(1).trim());
            }

            // 解析音频流信息 - 更灵活的正则表达式
            // 匹配类似: Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
            Pattern audioPattern = Pattern.compile(
                    "Stream.*Audio:\\s*([^,]+),\\s*(\\d+)\\s*Hz,\\s*([^,]+),\\s*([^,]+)(?:,\\s*(\\d+)\\s*kb/s)?",
                    Pattern.CASE_INSENSITIVE
            );
            Matcher audioMatcher = audioPattern.matcher(output);

            if (audioMatcher.find()) {
                info.setCodec(audioMatcher.group(1).trim());
                info.setSampleRate(Integer.parseInt(audioMatcher.group(2).trim()));

                // 解析声道数
                String channelInfo = audioMatcher.group(3).toLowerCase();
                if (channelInfo.contains("mono")) {
                    info.setChannels(1);
                } else if (channelInfo.contains("stereo")) {
                    info.setChannels(2);
                } else {
                    // 尝试从字符串中提取数字
                    Pattern channelPattern = Pattern.compile("(\\d+).*channel");
                    Matcher channelMatcher = channelPattern.matcher(channelInfo);
                    if (channelMatcher.find()) {
                        info.setChannels(Integer.parseInt(channelMatcher.group(1)));
                    } else {
                        // 默认猜测为立体声
                        info.setChannels(2);
                    }
                }

                // 解析比特率
                if (audioMatcher.group(5) != null) {
                    info.setBitrate(audioMatcher.group(5).trim() + " kb/s");
                }
            } else {
                // 如果上面的模式不匹配，尝试更简单的模式
                audioPattern = Pattern.compile("(\\d+)\\s*Hz.*Audio", Pattern.CASE_INSENSITIVE);
                audioMatcher = audioPattern.matcher(output);
                if (audioMatcher.find()) {
                    info.setSampleRate(Integer.parseInt(audioMatcher.group(1).trim()));
                    // 对于简单模式，我们假设是立体声
                    info.setChannels(2);
                }
            }

            // 解析时长 - 更通用的匹配
            Pattern durationPattern = Pattern.compile("Duration:\\s*([0-9:.]+)");
            Matcher durationMatcher = durationPattern.matcher(output);
            if (durationMatcher.find()) {
                info.setDuration(durationMatcher.group(1).trim());
            }

            // 如果成功解析到基本信息，则认为文件有效
            // 即使没有解析到所有信息，只要有时长信息，也认为文件基本有效
            if (info.getDuration() != null || info.getFormat() != null) {
                info.setValid(true);
            }

            // 如果没有任何信息被解析，尝试最后的手段
            if (!info.isValid()) {
                // 检查是否有基本的FFmpeg输出结构
                if (output.contains("Stream") && output.contains("Audio")) {
                    info.setValid(true);
                    System.out.println("使用启发式方法判断文件有效");
                }
            }

        } catch (Exception e) {
            System.err.println("解析音频信息时出错: " + e.getMessage());
            // 即使解析出错，我们也不立即标记为无效，而是使用启发式判断
            if (output.contains("Duration:") && output.contains("Stream")) {
                info.setValid(true);
                System.out.println("尽管解析出错，但根据FFmpeg输出判断文件可能有效");
            } else {
                info.setValid(false);
            }
        }
    }

    /**
     * 通用的FFmpeg命令执行方法
     */
    private static boolean executeFFmpegCommand(ProcessBuilder processBuilder, String processName) {
        processBuilder.redirectErrorStream(true);

        try {
            System.out.println("开始执行FFmpeg命令: " + processName);

            Process process = processBuilder.start();

            // 读取FFmpeg输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                // 过滤并显示进度信息
                if (line.contains("time=") || line.contains("size=") || line.contains("bitrate=")) {
                    System.out.println("[FFmpeg进度] " + line);
                }
            }

            // 等待进程完成，设置超时时间（300秒）
            boolean finished = process.waitFor(300, TimeUnit.SECONDS);

            if (finished) {
                int exitCode = process.exitValue();
                if (exitCode == 0) {
                    System.out.println(processName + " 处理成功完成！");
                    return true;
                } else {
                    System.err.println(processName + " 处理失败，FFmpeg退出码: " + exitCode);
                    return false;
                }
            } else {
                System.err.println(processName + " 处理超时，已终止进程");
                process.destroyForcibly(); // 强制终止进程
                return false;
            }

        } catch (IOException e) {
            System.err.println(processName + " IO异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        } catch (InterruptedException e) {
            System.err.println(processName + " 被中断: " + e.getMessage());
            Thread.currentThread().interrupt(); // 重新设置中断状态
            return false;
        } catch (Exception e) {
            System.err.println(processName + " 发生未知异常: " + e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 智能音频处理：根据输入格式自动选择最佳处理方式
     * @param inputFilePath 输入文件路径
     * @param outputFilePath 输出文件路径（可选，如果为null则自动生成）
     * @return 处理后的文件路径
     */
    public static String smartAudioProcessing(String inputFilePath, String outputFilePath) throws Exception {
        File inputFile = new File(inputFilePath);
        if (!inputFile.exists()) {
            throw new FileNotFoundException("输入文件不存在: " + inputFilePath);
        }

        // 如果未指定输出路径，则自动生成
        if (outputFilePath == null || outputFilePath.trim().isEmpty()) {
            outputFilePath = inputFile.getParent() + File.separator + "processed_" +
                    inputFile.getName().replaceFirst("[.][^.]+$", "") + ".wav";
        }

        // 确保输出目录存在
        File outputFile = new File(outputFilePath);
        File outputDir = outputFile.getParentFile();
        if (outputDir != null && !outputDir.exists()) {
            outputDir.mkdirs();
        }

        // 先检查音频质量
        AudioInfo audioInfo = getDetailedAudioInfo(inputFilePath);
        System.out.println("原始音频信息: " + audioInfo);
        System.out.println("音频质量评分: " + audioInfo.getQualityScore() + "/10");

        // 即使解析失败，也尝试处理文件，因为文件可能实际上是有效的
        if (!audioInfo.isValid()) {
            System.err.println("警告：无法完全解析音频信息，但将继续尝试处理文件");
            // 不抛出异常，继续处理
        }

        String fileName = inputFile.getName().toLowerCase();
        boolean success;

        if (fileName.endsWith(".mp4") || fileName.endsWith(".mov") || fileName.endsWith(".avi")) {
            System.out.println("检测到视频文件，提取并优化音频...");
            success = extractAndOptimizeAudio(inputFilePath, outputFilePath);
        } else if (fileName.endsWith(".wav")) {
            if (audioInfo.isValid() && audioInfo.meetsVoskRequirements()) {
                System.out.println("WAV文件已符合Vosk要求，无需额外处理");
                return inputFilePath; // 直接返回原文件
            } else {
                System.out.println("WAV文件进行优化处理...");
                success = optimizeWavAudio(inputFilePath, outputFilePath);
            }
        } else if (fileName.endsWith(".m4a") || fileName.endsWith(".aac") ||
                fileName.endsWith(".mp3") || fileName.endsWith(".flac")) {
            System.out.println("检测到音频文件，转换为优化WAV...");
            success = convertToOptimizedWav(inputFilePath, outputFilePath);
        } else {
            throw new UnsupportedOperationException("不支持的音频格式: " + fileName);
        }

        if (!success) {
            throw new RuntimeException("音频处理失败");
        }

        // 验证输出文件质量
        AudioInfo outputInfo = getDetailedAudioInfo(outputFilePath);
        System.out.println("处理后音频信息: " + outputInfo);
        System.out.println("处理后质量评分: " + outputInfo.getQualityScore() + "/10");

        if (outputInfo.isValid() && !outputInfo.meetsVoskRequirements()) {
            System.err.println("警告：输出文件可能不完全符合Vosk要求");
        }

        return outputFilePath;
    }

    /**
     * 简化的音频处理 - 跳过详细检查，直接处理
     * @param inputFilePath 输入文件路径
     * @param outputFilePath 输出文件路径（可选，如果为null则自动生成）
     * @return 处理后的文件路径
     */
    public static String simpleAudioProcessing(String inputFilePath, String outputFilePath) throws Exception {
        File inputFile = new File(inputFilePath);
        if (!inputFile.exists()) {
            throw new FileNotFoundException("输入文件不存在: " + inputFilePath);
        }

        // 如果未指定输出路径，则自动生成
        if (outputFilePath == null || outputFilePath.trim().isEmpty()) {
            outputFilePath = inputFile.getParent() + File.separator + "processed_" +
                    inputFile.getName().replaceFirst("[.][^.]+$", "") + ".wav";
        }

        // 确保输出目录存在
        File outputFile = new File(outputFilePath);
        File outputDir = outputFile.getParentFile();
        if (outputDir != null && !outputDir.exists()) {
            outputDir.mkdirs();
        }

        String fileName = inputFile.getName().toLowerCase();
        boolean success;

        if (fileName.endsWith(".mp4") || fileName.endsWith(".mov") || fileName.endsWith(".avi")) {
            System.out.println("检测到视频文件，提取并优化音频...");
            success = extractAndOptimizeAudio(inputFilePath, outputFilePath);
        } else if (fileName.endsWith(".wav")) {
            System.out.println("检测到WAV文件，进行优化处理...");
            success = optimizeWavAudio(inputFilePath, outputFilePath);
        } else if (fileName.endsWith(".m4a") || fileName.endsWith(".aac") ||
                fileName.endsWith(".mp3") || fileName.endsWith(".flac")) {
            System.out.println("检测到音频文件，转换为优化WAV...");
            success = convertToOptimizedWav(inputFilePath, outputFilePath);
        } else {
            throw new UnsupportedOperationException("不支持的音频格式: " + fileName);
        }

        if (!success) {
            throw new RuntimeException("音频处理失败");
        }

        return outputFilePath;
    }

    // ... (其他方法保持不变)

    /**
     * 使用示例和测试方法 - 改进版本，支持自定义输出路径
     */
    public static void main(String[] args) {
        // 配置输入和输出路径
        // String inputFile = "path/to/your/audio.mp4"; // 替换为实际输入文件路径
        // String outputFile = "path/to/your/output/audio_processed.wav"; // 替换为期望的输出文件路径

        String inputFile = "D:\\mp4totext\\mp4_testfile\\古籍修复.mp4";
        String outputFile = "D:\\mp4totext\\mp4_testfile\\wav\\古籍修复.wav";

        // 如果没有指定输出路径，可以设置为null，让程序自动生成
        // String outputFile = null;

        try {
            System.out.println("开始处理音频文件...");
            System.out.println("输入文件: " + inputFile);
            System.out.println("输出文件: " + (outputFile != null ? outputFile : "自动生成"));

            // 首先尝试完整处理
            try {
                String processedFile = smartAudioProcessing(inputFile, outputFile);
                System.out.println("\n智能处理完成！输出文件: " + processedFile);

                // 验证输出文件
                File resultFile = new File(processedFile);
                if (resultFile.exists() && resultFile.length() > 0) {
                    System.out.println("✓ 输出文件验证成功，大小: " + resultFile.length() + " 字节");
                } else {
                    System.err.println("✗ 输出文件验证失败");
                }

            } catch (Exception e) {
                System.err.println("智能处理失败，尝试简化处理: " + e.getMessage());

                // 如果智能处理失败，尝试简化处理
                String processedFile = simpleAudioProcessing(inputFile, outputFile);
                System.out.println("\n简化处理完成！输出文件: " + processedFile);

                // 验证输出文件
                File resultFile = new File(processedFile);
                if (resultFile.exists() && resultFile.length() > 0) {
                    System.out.println("✓ 输出文件验证成功，大小: " + resultFile.length() + " 字节");
                } else {
                    System.err.println("✗ 输出文件验证失败");
                }
            }

        } catch (Exception e) {
            System.err.println("所有处理尝试都失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 命令行版本 - 支持从命令行参数指定输入输出文件
     */
    public static void mainWithArgs(String[] args) {
        if (args.length == 0) {
            System.out.println("用法: java EnhancedAudioProcessor <输入文件> [输出文件]");
            System.out.println("示例:");
            System.out.println("  java EnhancedAudioProcessor input.mp4");
            System.out.println("  java EnhancedAudioProcessor input.mp4 output.wav");
            return;
        }

        String inputFile = args[0];
        String outputFile = args.length > 1 ? args[1] : null;

        try {
            System.out.println("开始处理音频文件...");
            System.out.println("输入文件: " + inputFile);
            System.out.println("输出文件: " + (outputFile != null ? outputFile : "自动生成"));

            // 首先尝试完整处理
            try {
                String processedFile = smartAudioProcessing(inputFile, outputFile);
                System.out.println("\n智能处理完成！输出文件: " + processedFile);
            } catch (Exception e) {
                System.err.println("智能处理失败，尝试简化处理: " + e.getMessage());

                // 如果智能处理失败，尝试简化处理
                String processedFile = simpleAudioProcessing(inputFile, outputFile);
                System.out.println("\n简化处理完成！输出文件: " + processedFile);
            }

        } catch (Exception e) {
            System.err.println("所有处理尝试都失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
